﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "../xos/head.h"
#include "event_impl.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos
{
    ////////////////////////////////////////////////////////////////////////////////////
    // 

    static event_impl::POOL * pool_ptr = 0;

    ////////////////////////////////////////////////////////////////////////////////////
    //

    event_impl::event_impl()
    {
        memset( m_nPipe, -1, sizeof( m_nPipe ) );
        m_nWriteNum = 0;
    }

    event_impl::~event_impl()
    {
        term();
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    int event_impl::get_addr( POOL *** pppPool, LIST *** pppList )
    {
        int ret = 0;
        if( pppPool )
        {
            *pppPool = &pool_ptr;
        }
        if( pppList )
        {
            *pppList = 0;
        }
        return ret;
    }

    int event_impl::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = pipe( m_nPipe );
        }

        for( int i = 0; ( 0 == ret ) && ( i < 2 ); ++i )
        {
            int opts = fcntl( m_nPipe[i], F_GETFL );
            if( opts >= 0 )
            {
                opts = opts | O_NONBLOCK;
                fcntl( m_nPipe[i], F_SETFL, opts );
            }
        }

        return ret;
    }

    int event_impl::term()
    {
        int ret = 0;

        for( int i = 0; ( 0 == ret ) && ( i < 2 ); ++i )
        {
            close( m_nPipe[i] );
            m_nPipe[i] = -1;
        }

        m_nWriteNum = 0;

        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    unsigned long event_impl::wait( unsigned long ulMilliseconds )
    {
        unsigned long ulRet = EVENT_WAIT_OBJECT_0;
        int ret = 0;

        struct timeval tm = { 0 }, * pTm = 0;
        int hRead = m_nPipe[0];

        if( ( 0 == ret ) && ( 0 == m_nWriteNum ) && ( EVENT_WAIT_INFINITE != ulMilliseconds ) )
        {
            tm.tv_usec = ( ulMilliseconds % 1000 ) * 1000;
            tm.tv_sec = ulMilliseconds / 1000;
            pTm = &tm;
        }

        if( ( 0 == ret ) && ( 0 == m_nWriteNum ) )
        {
            fd_set fdR;
            FD_ZERO( &fdR );
            FD_SET( hRead, &fdR );
            int r = select( hRead + 1, &fdR, 0, 0, pTm );
            if( 1 == r )
            {
            }
            else if( 0 == r )
            {
                ulRet = EVENT_WAIT_TIMEOUT;
                ret = 1;
            }
            else
            {
                ulRet = EVENT_WAIT_FAILED;
                ret = 1;
            }
        }

        if( ( 0 == ret ) && ( m_nWriteNum > 0 ) )
        {
            char buf[1024];
            ::read( hRead, buf, sizeof( buf ) );
            m_nWriteNum = 0;
        }

        return ulRet;
    }

    int event_impl::set_event()
    {
        int ret = 0;

        if( 0 == m_nWriteNum )
        {
            m_nWriteNum++;
            ::write( m_nPipe[1], "1", 1 );
        }

        return ret;
    }
} // xos
